package igloo.aws;

import java.util.concurrent.ExecutorService;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.services.glacier.AmazonGlacierClient;
import com.amazonaws.services.glacier.model.CreateVaultRequest;
import com.amazonaws.services.glacier.model.CreateVaultResult;
import com.amazonaws.services.glacier.model.DeleteArchiveRequest;
import com.amazonaws.services.glacier.model.DeleteVaultRequest;
import com.amazonaws.services.glacier.model.DescribeJobRequest;
import com.amazonaws.services.glacier.model.DescribeJobResult;
import com.amazonaws.services.glacier.model.DescribeVaultRequest;
import com.amazonaws.services.glacier.model.DescribeVaultResult;
import com.amazonaws.services.glacier.model.GetJobOutputRequest;
import com.amazonaws.services.glacier.model.GetJobOutputResult;
import com.amazonaws.services.glacier.model.InitiateJobRequest;
import com.amazonaws.services.glacier.model.InitiateJobResult;
import com.amazonaws.services.glacier.model.ListVaultsRequest;
import com.amazonaws.services.glacier.model.ListVaultsResult;
import com.amazonaws.services.glacier.model.UploadArchiveRequest;
import com.amazonaws.services.glacier.model.UploadArchiveResult;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;

public class IglooGlacierClient
{
    private AWSCredentials mCredentials;
    private Region mRegion;

    private AmazonGlacierClient mClient;

    private final ExecutorService mExecutor;

    public IglooGlacierClient(AWSCredentials credentials, Region region, ExecutorService executor)
    {
        mCredentials = credentials;
        mRegion = region;

        mClient = new AmazonGlacierClient(mCredentials);
        mClient.setEndpoint(mRegion.getEndpoint());

        mExecutor = executor;
    }

    public AWSCredentials getCredentials()
    {
        return mCredentials;
    }

    public AmazonGlacierClient getClient()
    {
        return mClient;
    }

    public Region getRegion()
    {
        return mRegion;
    }

    public ListenableFuture<CreateVaultResult> createVault(final CreateVaultRequest request)
    {
        final SettableFuture<CreateVaultResult> future = SettableFuture.create();

        mExecutor.execute(new Runnable() {
            @Override
            public void run()
            {
                try
                {
                    CreateVaultResult result = mClient.createVault(request);
                    future.set(result);
                }
                catch(Exception e)
                {
                    future.setException(e);
                }
            }
        });

        return future;
    }

    public ListenableFuture<DescribeVaultResult> describeVault(final DescribeVaultRequest request)
    {
        final SettableFuture<DescribeVaultResult> future = SettableFuture.create();

        mExecutor.execute(new Runnable() {
            @Override
            public void run()
            {
                try
                {
                    DescribeVaultResult result = mClient.describeVault(request);
                    future.set(result);
                }
                catch(Exception e)
                {
                    future.setException(e);
                }
            }
        });

        return future;
    }

    public ListenableFuture<ListVaultsResult> listVaults(final ListVaultsRequest request)
    {
        final SettableFuture<ListVaultsResult> future = SettableFuture.create();

        mExecutor.execute(new Runnable() {
            @Override
            public void run()
            {
                try
                {
                    ListVaultsResult result = mClient.listVaults(request);
                    future.set(result);
                }
                catch(Exception e)
                {
                    future.setException(e);
                }
            }
        });

        return future;
    }

    public ListenableFuture<Boolean> deleteVault(final DeleteVaultRequest request)
    {
        final SettableFuture<Boolean> future = SettableFuture.create();

        mExecutor.execute(new Runnable() {
            @Override
            public void run()
            {
                try
                {
                    mClient.deleteVault(request);
                    future.set(true);
                }
                catch(Exception e)
                {
                    future.setException(e);
                }
            }
        });

        return future;
    }

    public ListenableFuture<UploadArchiveResult> uploadArchive(final UploadArchiveRequest request)
    {
        final SettableFuture<UploadArchiveResult> future = SettableFuture.create();

        mExecutor.execute(new Runnable() {
            @Override
            public void run()
            {
                try
                {
                    UploadArchiveResult result = mClient.uploadArchive(request);
                    future.set(result);
                }
                catch(Exception e)
                {
                    future.setException(e);
                }
            }
        });

        return future;
    }

    public void deleteArchive(final DeleteArchiveRequest request)
    {
        mExecutor.execute(new Runnable() {
            @Override
            public void run()
            {
                try
                {
                    mClient.deleteArchive(request);
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
            }
        });
    }

    public ListenableFuture<InitiateJobResult> initiateJob(final InitiateJobRequest request)
    {
        final SettableFuture<InitiateJobResult> future = SettableFuture.create();

        mExecutor.execute(new Runnable() {
            @Override
            public void run()
            {
                try
                {
                    InitiateJobResult result = mClient.initiateJob(request);
                    future.set(result);
                }
                catch(Exception e)
                {
                    future.setException(e);
                }
            }
        });

        return future;
    }

    public ListenableFuture<DescribeJobResult> describeJob(final DescribeJobRequest request)
    {
        final SettableFuture<DescribeJobResult> future = SettableFuture.create();

        mExecutor.execute(new Runnable() {
            @Override
            public void run()
            {
                try
                {
                    DescribeJobResult result = mClient.describeJob(request);
                    future.set(result);
                }
                catch(Exception e)
                {
                    future.setException(e);
                }
            }
        });

        return future;
    }

    public ListenableFuture<GetJobOutputResult> getJobOutput(final GetJobOutputRequest request)
    {
        final SettableFuture<GetJobOutputResult> future = SettableFuture.create();

        mExecutor.execute(new Runnable() {
            @Override
            public void run()
            {
                try
                {
                    GetJobOutputResult result = mClient.getJobOutput(request);
                    future.set(result);
                }
                catch(Exception e)
                {
                    future.setException(e);
                }
            }
        });

        return future;
    }
}
